<template>
  <div v-transfer-dom>
    <transition :name="transitionNames[1]">
      <div :class="maskClasses" v-show="visible" @click="mask"></div>
    </transition>
    <div :class="wrapClasses" @click="handleWrapClick">
      <transition :name="transitionNames[0]">
        <div :class="classes" :style="mainStyles" v-show="visible">
          <div :class="[prefixCls + '-content']">
            <a :class="[prefixCls + '-close']" v-if="closable" @click="close">
              <slot name="close">
                <oolongIcon type="ios-close-empty"></oolongIcon>
              </slot>
            </a>
            <div :class="[prefixCls + '-header']" v-if="showHead">
              <slot name="header">
                <div
                  :class="[prefixCls + '-header-inner']">{{ title }}
                </div>
              </slot>
            </div>
            <div :class="[prefixCls + '-body']">
              <slot></slot>
            </div>
            <div :class="[prefixCls + '-footer']" v-if="!footerHide">
              <slot name="footer">
                <oolongButton type="text" size="large" @click.native="cancel">{{
                    localeCancelText
                  }}
                </oolongButton>
                <oolongButton type="primary" size="large" :loading="buttonLoading"
                              @click.native="ok">{{ localeOkText }}
                </oolongButton>
              </slot>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </div>
</template>
<script>
import oolongIcon from '../icon';
import oolongButton from '../button';
import TransferDom from '../../directives/transfer-dom';
import {getScrollBarSize} from '../../utils/assist';
import Locale from '../../mixins/locale';
import Emitter from '../../mixins/emitter';

const prefixCls = 'oolong-modal';

export default {
  name: 'oolongDialong',
  mixins: [Locale, Emitter],
  components: {oolongIcon, oolongButton},
  directives: {TransferDom},
  props: {
    value: {
      type: Boolean,
      default: false
    },
    closable: {
      type: Boolean,
      default: true
    },
    maskClosable: {
      type: Boolean,
      default: true
    },
    title: {
      type: String
    },
    width: {
      type: [Number, String],
      default: 520
    },
    okText: {
      type: String
    },
    cancelText: {
      type: String
    },
    loading: {
      type: Boolean,
      default: false
    },
    styles: {
      type: Object
    },
    className: {
      type: String
    },
    // for instance
    footerHide: {
      type: Boolean,
      default: false
    },
    scrollable: {
      type: Boolean,
      default: false
    },
    transitionNames: {
      type: Array,
      default() {
        return ['ease', 'fade'];
      }
    }
  },
  data() {
    return {
      prefixCls: prefixCls,
      wrapShow: false,
      showHead: true,
      buttonLoading: false,
      visible: this.value
    };
  },
  computed: {
    wrapClasses() {
      return [
        `${prefixCls}-wrap`,
        {
          [`${prefixCls}-hidden`]: !this.wrapShow,
          [`${this.className}`]: !!this.className
        }
      ];
    },
    maskClasses() {
      return `${prefixCls}-mask`;
    },
    classes() {
      return `${prefixCls}`;
    },
    mainStyles() {
      let style = {};

      const styleWidth = {
        width: `${this.width}px`
      };

      const customStyle = this.styles ? this.styles : {};

      Object.assign(style, styleWidth, customStyle);

      return style;
    },
    localeOkText() {
      if (this.okText === undefined) {
        return this.t('i.modal.okText');
      } else {
        return this.okText;
      }
    },
    localeCancelText() {
      if (this.cancelText === undefined) {
        return this.t('i.modal.cancelText');
      } else {
        return this.cancelText;
      }
    }
  },
  methods: {
    close() {
      this.visible = false;
      this.$emit('input', false);
      this.$emit('on-cancel');
    },
    mask() {
      if (this.maskClosable) {
        this.close();
      }
    },
    handleWrapClick(event) {
      // use indexOf,do not use === ,because oolong-modal-wrap can have other custom className
      const className = event.target.getAttribute('class');
      if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.mask();
    },
    cancel() {
      this.close();
    },
    ok() {
      if (this.loading) {
        this.buttonLoading = true;
      } else {
        this.visible = false;
        this.$emit('input', false);
      }
      this.$emit('on-ok');
    },
    EscClose(e) {
      if (this.visible && this.closable) {
        if (e.keyCode === 27) {
          this.close();
        }
      }
    },
    checkScrollBar() {
      let fullWindowWidth = window.innerWidth;
      if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
        const documentElementRect = document.documentElement.getBoundingClientRect();
        fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
      }
      this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
      if (this.bodyIsOverflowing) {
        this.scrollBarWidth = getScrollBarSize();
      }
    },
    setScrollBar() {
      if (this.bodyIsOverflowing && this.scrollBarWidth !== undefined) {
        document.body.style.paddingRight = `${this.scrollBarWidth}px`;
      }
    },
    resetScrollBar() {
      document.body.style.paddingRight = '';
    },
    addScrollEffect() {
      this.checkScrollBar();
      this.setScrollBar();
      document.body.style.overflow = 'hidden';
    },
    removeScrollEffect() {
      document.body.style.overflow = '';
      this.resetScrollBar();
    }
  },
  mounted() {
    if (this.visible) {
      this.wrapShow = true;
    }

    let showHead = true;

    if (this.$slots.header === undefined && !this.title) {
      showHead = false;
    }

    this.showHead = showHead;

    // ESC close
    document.addEventListener('keydown', this.EscClose);
  },
  beforeDestroy() {
    document.removeEventListener('keydown', this.EscClose);
    this.removeScrollEffect();
  },
  watch: {
    value(val) {
      this.visible = val;
    },
    visible(val) {
      if (val === false) {
        this.buttonLoading = false;
        this.timer = setTimeout(() => {
          this.wrapShow = false;
          this.removeScrollEffect();
        }, 300);
      } else {
        if (this.timer) clearTimeout(this.timer);
        this.wrapShow = true;
        if (!this.scrollable) {
          this.addScrollEffect();
        }
      }
      this.broadcast('oolongTable', 'on-visible-change', val);
    },
    loading(val) {
      if (!val) {
        this.buttonLoading = false;
      }
    },
    scrollable(val) {
      if (!val) {
        this.addScrollEffect();
      } else {
        this.removeScrollEffect();
      }
    },
    title(val) {
      if (this.$slots.header === undefined) {
        this.showHead = !!val;
      }
    }
  }
};
</script>
